import type Fetch from './Fetch';

export type Timeout = ReturnType<typeof setTimeout>;

// export type Service<TData = any, TRunArgs extends any[] = any[]> = (...args: TRunArgs) => Promise<TData>;
export type Service<TData = any, TRunArgs extends any[] = any[]> = (...args: TRunArgs) => Promise<TData>;

export interface Options<TData = any, TRunArgs = any[]> {
  onBefore?: (runArgs: TRunArgs) => void;
  onSuccess?: (data: TData, runArgs: TRunArgs) => void;
  onError?: (e: Error, runArgs: TRunArgs) => void;
  onFinally?: (runArgs: TRunArgs, data?: TData, e?: Error) => void;

  // loading delay
  loadingDelay?: number; //设置 loading 变成 true 的延迟时间

  // polling
  pollingInterval?: number;
  pollingWhenHidden?: boolean;
  pollingErrorRetryCount?: number;

  // refresh on window focus
  refreshOnWindowFocus?: boolean;
  focusTimespan?: number; //重新请求间隔，单位为毫秒

  // cache
  cacheKey?: string;
  cacheTime?: number; //缓存数据被删除的时间
  staleTime?: number; //缓存数据被删除的时间还没到，就想重新请求数据更新缓存数据，可以理解为保鲜时间

  // retry
  retryCount?: number;
  retryInterval?: number;
}

export interface FetchState<TData = any, TRunArgs = any[]> {
  loading: boolean;
  data?: TData;
  error?: Error;
  runArgs?: TRunArgs;
}

export interface Result<TData = any, TRunArgs extends any[] = any[]> extends FetchState<TData, TRunArgs> {
  loading: boolean;
  data?: TData;
  error?: Error;
  params: TRunArgs | undefined;
  cancel: Fetch<TData, TRunArgs>['cancel'];
  refresh: Fetch<TData, TRunArgs>['refresh'];
  refreshAsync: Fetch<TData, TRunArgs>['refreshAsync'];
  run: Fetch<TData, TRunArgs>['run'];
  runAsync: Fetch<TData, TRunArgs>['runAsync'];
  mutate: Fetch<TData, TRunArgs>['mutate'];
}

export interface PluginReturn<TData = any, TRunArgs extends any[] = any[]> {
  onBefore?: (runArgs: TRunArgs) => void;
  onRequest?: (service: Service<TData, TRunArgs>, runArgs: TRunArgs) => Promise<TData>;
  onSuccess?: (data: TData, runArgs: TRunArgs) => void;
  onError?: (e: Error, runArgs: TRunArgs) => void;
  onFinally?: (runArgs: TRunArgs, data?: TData, e?: Error) => void;
  onCancel?: () => void;
  onMutate?: (data: TData) => void;
}

export type Plugins<TData = any, TRunArgs extends any[] = any[]> = (fetchInstance: Fetch<TData, TRunArgs>, options: Options<TData, TRunArgs>) => PluginReturn<TData, TRunArgs>;

export type TUseRequestHandler<TData = any, TRunArgs extends any[] = any[]> = (service: Service<TData, TRunArgs>, options?: Options<TData, TRunArgs>) => Result<TData, TRunArgs>;